package com.ucode.application.controller.crm;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.validation.constraints.Size;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.ucode.application.form.crm.ContactsForm;
import com.ucode.application.helper.CrmDataPermissionVerifier;
import com.ucode.application.security.CurrentLoginUserService;
import com.ucode.crm.dictionary.CrmResultDefineMsg;
import com.ucode.crm.dictionary.ModuleType;
import com.ucode.crm.dictionary.TeamUserPower;
import com.ucode.crm.mode.Contacts;
import com.ucode.crm.mode.Customer;
import com.ucode.crm.service.ContactsService;
import com.ucode.crm.service.CustomerService;
import com.ucode.crm.vo.ContactsVo;
import com.ucode.search.crm.model.ESContacts;
import com.ucode.search.crm.service.ESContactsService;
import com.ucode.springboot.starter.web.validator.group.AddGroup;
import com.ucode.sys.model.User;
import com.ucode.sys.service.UserService;
import com.ucode.tool.base.Paginator;
import com.ucode.tool.base.ResponseResult;
import com.ucode.tool.base.ResultCodeEnum;
import com.ucode.tool.exception.UcodeServiceException;
import cn.hutool.core.collection.CollUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@Api(tags="CRM-联系人")
@RestController
@RequestMapping("/crm-contacts")
@Validated
public class ContactsController {
    private static final String moduleCode = "crm";
    
    @Autowired
    private CustomerService customerService;
    @Autowired
    private ContactsService contactsService;
    @Autowired
    private UserService userService;
    @Autowired
    private CurrentLoginUserService currentLoginUserService;
    @Autowired
    private CrmDataPermissionVerifier dataPermissionVerifier;
    @Autowired
    private ESContactsService esContactsService;

    @PreAuthorize("hasAuthority('crm:contacts:list') or hasRole('ADMIN') or hasRole('CRMADMIN')")
    @ApiOperation("联系人列表")
    @GetMapping(value = "/list")
    public ResponseResult<Object> list(
            @ApiParam(value ="联系人名称/电话/手机号")  @RequestParam(value = "keywords") String keyword,
            @ApiParam(value="页码",example="1") @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @ApiParam(value="每页记录数",example="20") @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize){
        Paginator<ContactsVo> vopag = null;
        List<Long> userIds = dataPermissionVerifier.getCheckCurrentUserManageUsers(moduleCode, null);
        if(userIds != null && userIds.size() == 0){
            vopag = new Paginator<>(0, pageNum, pageSize);
            return ResponseResult.success(vopag);
        }
        try {
            Paginator<ESContacts> paginator = esContactsService.searchByUser(userIds, keyword, pageNum, pageSize);
            if(paginator != null && CollUtil.isNotEmpty(paginator.getList())){
                List<ESContacts> list = paginator.getList();
                
                List<Long> contactsIds = new ArrayList<Long>();
                Set<Long> customerIds = new HashSet<Long>();
                Set<Long> userIds1 = new HashSet<Long>(); 
                for(ESContacts esContacts : list){
                    contactsIds.add(esContacts.getId());
                    customerIds.add(esContacts.getCustomerId());
                    userIds1.add(esContacts.getCreateUserId());
                }
                
                CompletableFuture<Map<Long, Contacts>> completableFutureContacts = CompletableFuture.supplyAsync(() -> {
                    try {
                        List<Contacts> clist = contactsService.findByIds(contactsIds);
                        Map<Long, Contacts> customerMap = clist.stream().collect(Collectors.toMap(Contacts::getId,Function.identity(),(key1, key2) -> key1));
                        return customerMap;
                    } catch (Exception e) {
                    }
                    return new HashMap<>();
                });
                
                CompletableFuture<Map<Long, String>> completableFutureUser = CompletableFuture.supplyAsync(() -> {
                    try {
                        List<User> ulist = userService.findByIds(new ArrayList<>(userIds1));
                        Map<Long, String> customerMap = ulist.stream().collect(Collectors.toMap(User::getId,User::getRealname,(key1, key2) -> key1));
                        return customerMap;
                    } catch (Exception e) {
                    }
                    return new HashMap<>();
                });
                
                CompletableFuture<Map<Long, String>> completableFutureCustomer = CompletableFuture.supplyAsync(() -> {
                    try {
                        List<Customer> customers = customerService.findByIds(new ArrayList<>(customerIds));
                        Map<Long, String> customerMap = customers.stream().collect(Collectors.toMap(Customer::getId,Customer::getName,(key1, key2) -> key1));
                        return customerMap;
                    } catch (Exception e) {
                    }
                    return new HashMap<>();
                });
                
                Map<Long, Contacts> cMap = completableFutureContacts.get();
                Map<Long, String> uMap = completableFutureUser.get();
                Map<Long, String> cmMap = completableFutureCustomer.get();
                
                List<ContactsVo> contactsVos = new ArrayList<>();
                vopag = new Paginator<>(paginator.getTotal(), paginator.getCurrentPage(), paginator.getRows());
                for(ESContacts esContacts : list){
                    Contacts contacts = cMap.get(esContacts.getId());
                    String createUser = uMap.get(esContacts.getCreateUserId());
                    String customerName = cmMap.get(esContacts.getCustomerId()); 
                    contactsVos.add(new ContactsVo(contacts, null, createUser, customerName));
                }
                
                vopag.setList(contactsVos);
                
            }
            return ResponseResult.success(vopag);
        } catch (Exception e) {
            throw new UcodeServiceException(ResultCodeEnum.SERVER_ERROR);
        }
    }
    
    @PreAuthorize("hasAuthority('crm:contacts:detail') or hasRole('ADMIN') or hasRole('CRMADMIN')")
    @ApiOperation(value="详情信息")
    @ApiImplicitParam(name = "id", value = "主键ID", required = true, dataType = "String",paramType = "path")
    @GetMapping("/detail/{id}")
    public ResponseResult<Object> detail(@PathVariable(name="id",required=true) Long id){
        
        Contacts contacts = contactsService.findById(id);
        if(contacts == null || contacts.getDeltag() == 1){
            throw new UcodeServiceException(ResultCodeEnum.NO_RECORD.code,"联系人已删除");
        }
        
        Long ownerUserId = contacts.getOwnerUserId();
        Integer power =  TeamUserPower.read.code;
        if(ownerUserId != null && !ownerUserId.equals(0L)){
            List<Long> ownerUserIds = Arrays.asList(ownerUserId);
            power = dataPermissionVerifier.getCurrentUserPowerByBusinessData(moduleCode, ModuleType.customer, contacts.getCustomerId(), ownerUserIds);
        }
        
        Customer customer = customerService.findById(contacts.getCustomerId());
        User user = userService.findById(customer.getCreateUserId());
        
        ContactsVo contactsVo = new ContactsVo(contacts, power, user == null ? "" : user.getRealname(), customer ==null ? "" : customer.getName());
        
        return ResponseResult.success(contactsVo);
    }
    
    
    @PreAuthorize("hasAuthority('crm:contacts:edit') or hasRole('ADMIN') or hasRole('CRMADMIN')")
    @ApiOperation(value="根据主键查询")
    @ApiImplicitParam(name = "id", value = "主键ID", required = true, dataType = "String",paramType = "path")
    @GetMapping("/getById/{id}")
    public ResponseResult<Object> getById(@PathVariable(name="id",required=true) Long id){
        
        Contacts contacts = contactsService.findById(id);
        if(contacts == null || contacts.getDeltag() == 1){
            throw new UcodeServiceException(ResultCodeEnum.NO_RECORD.code,"联系人已删除");
        }
        
        Long ownerUserId = contacts.getOwnerUserId();
        if(ownerUserId == null || ownerUserId.equals(0L)){
            throw new UcodeServiceException(ResultCodeEnum.ILLEGAL_OPERATION.code,CrmResultDefineMsg.customer_pool_edit_contacts_error);
        }
        
        List<Long> ownerUserIds = Arrays.asList(ownerUserId);
        
        //校验数据编辑权限
        dataPermissionVerifier.checkCurrentUserWritePowerByBusinessData(moduleCode, ModuleType.customer, contacts.getCustomerId(), ownerUserIds, CrmResultDefineMsg.contacts_edit_permission_error,contacts.getName());
        
        Customer customer = customerService.findById(contacts.getCustomerId());
        ContactsVo contactsVo = new ContactsVo(contacts, null, null, customer ==null ? "" : customer.getName());
        
        return ResponseResult.success(contactsVo);
    }
    
    
    @PreAuthorize("hasAuthority('crm:contacts:edit') or hasRole('CRMADMIN') or hasRole('ADMIN')")
    @ApiOperation(value="创建")
    @PostMapping("/create")
    public ResponseResult<Object> create(@Validated({AddGroup.class}) @RequestBody ContactsForm form) {
        Customer customer = customerService.findById(form.getCustomerId());
        if(customer == null || customer.getDeltag() == 1){
            throw new UcodeServiceException(ResultCodeEnum.NO_RECORD.code,CrmResultDefineMsg.contacts_add_customer_deleted_error);
        }
        
        if(customer.getOwnerUserId() == null || customer.getOwnerUserId().equals(0L)){
            throw new UcodeServiceException(ResultCodeEnum.FAILED.code,CrmResultDefineMsg.customer_pool_add_contacts_error);
        }
        
        //校验数据编辑权限
        dataPermissionVerifier.checkCurrentUserWritePowerByBusinessData(moduleCode, ModuleType.customer, customer.getId(),  Arrays.asList(customer.getOwnerUserId()), CrmResultDefineMsg.contacts_add_permission_error);
         
        Long currentUserId = currentLoginUserService.getCurrentUserId();
        
        Contacts contacts = new Contacts(form.getName(), form.getMobile(), form.getTelephone(), form.getEmail(), form.getWechat(), form.getQq(), form.getDm(), form.getJob(), form.getBirthday(), form.getSex(), form.getAddress(), form.getRemark());
        contacts.setCustomerId(customer.getId());
        contacts.setCreateUserId(currentUserId);
        contacts.setOwnerUserId(customer.getOwnerUserId());
        contacts = contactsService.insert(contacts);
        
        return ResponseResult.success(contacts);
    }
    
    
    @PreAuthorize("hasAuthority('crm:contacts:edit') or hasRole('CRMADMIN') or hasRole('ADMIN')")
    @ApiOperation(value="更新")
    @ApiImplicitParam(name = "id", value = "联系人ID", required = true, dataType = "String",paramType = "path")
    @PostMapping("/update/{id}")
    public ResponseResult<Object> update(@PathVariable(name="id",required=true) Long id,
            @Validated({AddGroup.class}) @RequestBody ContactsForm form) {
        
        Contacts dbcontacts = contactsService.findById(id);
        if(dbcontacts == null || dbcontacts.getDeltag() == 1){
            throw new UcodeServiceException(ResultCodeEnum.NO_RECORD);
        }
        
        if(dbcontacts.getOwnerUserId() == null || dbcontacts.getOwnerUserId().equals(0L)){
            throw new UcodeServiceException(ResultCodeEnum.FAILED.code,CrmResultDefineMsg.customer_pool_edit_contacts_error);
        }
        
        //校验数据编辑权限
        dataPermissionVerifier.checkCurrentUserWritePowerByBusinessData(moduleCode, ModuleType.customer, dbcontacts.getCustomerId(), Arrays.asList(dbcontacts.getOwnerUserId()), CrmResultDefineMsg.contacts_edit_permission_error,dbcontacts.getName());
        
        Contacts contacts = new Contacts(form.getName(), form.getMobile(), form.getTelephone(), form.getEmail(), form.getWechat(), form.getQq(), form.getDm(), form.getJob(), form.getBirthday(), form.getSex(), form.getAddress(), form.getRemark());
        contacts.setId(id);
        
        int i = contactsService.update(contacts);
        
        return i > 0 ? ResponseResult.success() : ResponseResult.failed();
    }
    
    @PreAuthorize("hasAuthority('crm:contacts:delete') or hasRole('CRMADMIN') or hasRole('ADMIN')")
    @ApiOperation(value="删除联系人")
    @PostMapping("/delete")
    public ResponseResult<Object> delete(
            @ApiParam(value="联系人Ids",required=true) @Size(min = 1,max=20,message="一次能操作1-20条记录")@RequestParam(value = "ids", required=true) List<Long> ids) {
        
        List<Contacts> contactsList = contactsService.findByIds(ids);
        if(CollUtil.isNotEmpty(contactsList)){
             for(Contacts contacts : contactsList){
//                Long ownerUserId = contacts.getOwnerUserId();
                if(contacts.getDeltag() == 1)
                    continue;
                
                if(contacts.getOwnerUserId() == null || contacts.getOwnerUserId().equals(0L))
                    throw new UcodeServiceException(ResultCodeEnum.FAILED.code,CrmResultDefineMsg.contacts_delete_permission_error,contacts.getName());
                
                if(contacts.getDc() == 0)
                    throw new UcodeServiceException(ResultCodeEnum.FAILED.code,CrmResultDefineMsg.contacts_dc_delete_error,contacts.getName());
                
                //校验权限
                dataPermissionVerifier.checkCurrentUserOwnerPowerByBusinessData(moduleCode,ModuleType.customer, Arrays.asList(contacts.getOwnerUserId()), CrmResultDefineMsg.contacts_delete_permission_error, contacts.getName());
                
                contactsService.deleteByLogic(contacts.getId());
            }
        }
        return ResponseResult.success();
        
    }
    
    @PreAuthorize("hasAuthority('crm:contacts:edit') or hasRole('ADMIN')")
    @ApiOperation(value="设置首要联系人")
    @ApiImplicitParam(name = "id", value = "联系人ID", required = true, dataType = "String",paramType = "path")
    @PostMapping("/setDc/{id}")
    public ResponseResult<Object> setDc(@PathVariable(name="id",required=true) Long id) {
        
        Contacts dbcontacts = contactsService.findById(id);
        if(dbcontacts == null || dbcontacts.getDeltag() == 1){
            throw new UcodeServiceException(ResultCodeEnum.NO_RECORD);
        }
        
        if(dbcontacts.getOwnerUserId() == null || dbcontacts.getOwnerUserId().equals(0L))
            throw new UcodeServiceException(ResultCodeEnum.FAILED.code,CrmResultDefineMsg.customer_setdc_permission_error);
        
        //校验权限
        dataPermissionVerifier.checkCurrentUserOwnerPowerByBusinessData(moduleCode,ModuleType.customer, Arrays.asList(dbcontacts.getOwnerUserId()), CrmResultDefineMsg.customer_setdc_permission_error);
        
        int i = contactsService.updateDc(id);
    
        return i > 0 ? ResponseResult.success() : ResponseResult.failed();
    
    }
}
